home *** CD-ROM | disk | FTP | other *** search
Text File | 1997-04-16 | 55.1 KB | 1,345 lines |
- Copyright (C) 1989, 1996 Aladdin Enterprises. All rights reserved.
-
- This file is part of Aladdin Ghostscript.
-
- Aladdin Ghostscript is distributed with NO WARRANTY OF ANY KIND. No author
- or distributor accepts any responsibility for the consequences of using it,
- or for whether it serves any particular purpose or works at all, unless he
- or she says so in writing. Refer to the Aladdin Ghostscript Free Public
- License (the "License") for full details.
-
- Every copy of Aladdin Ghostscript must include a copy of the License,
- normally in a plain ASCII text file named PUBLIC. The License grants you
- the right to copy, modify and redistribute Aladdin Ghostscript, but only
- under certain conditions described in the License. Among other things, the
- License requires that the copyright notice and this notice be preserved on
- all copies.
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- This file, drivers.txt, describes the interface between Ghostscript and
- device drivers.
-
- For an overview of Ghostscript and a list of the documentation files, see
- README.
-
- ********
- ******** Adding a driver ********
- ********
-
- To add a driver to Ghostscript, all you need to do is edit devs.mak in
- two places. The first is the list of devices, in the section headed
-
- # -------------------------------- Catalog ------------------------------- #
-
- Pick a name for your device, say smurf, and add smurf to the list.
- (Device names must be 1 to 8 characters, consisting of only letters,
- digits, and underscores, of which the first character must be a letter.
- Case is significant: all current device names are lower case.)
- The second is the section headed
-
- # ---------------------------- Device drivers ---------------------------- #
-
- Suppose the files containing the smurf driver are called joe and fred.
- Then you should add the following lines:
-
- # ------ The SMURF device ------ #
-
- smurf_=joe.$(OBJ) fred.$(OBJ)
- smurf.dev: $(smurf_)
- $(SETDEV) smurf $(smurf_)
-
- joe.$(OBJ): joe.c ...and whatever it depends on
-
- fred.$(OBJ): fred.c ...and whatever it depends on
-
- If the smurf driver also needs special libraries, e.g., a library named
- gorf, then the entry should look like this:
-
- smurf.dev: $(smurf_)
- $(SETDEV) smurf $(smurf_)
- $(ADDMOD) smurf -lib gorf
-
- If, as will usually be the case, your driver is a printer driver (as
- discussed below), the device entry should look like this:
-
- smurf.dev: $(smurf_) page.dev
- $(SETPDEV) smurf $(smurf_)
-
- or
-
- smurf.dev: $(smurf_) page.dev
- $(SETPDEV) smurf $(smurf_)
- $(ADDMOD) smurf -lib gorf
-
- ********
- ******** Keeping things simple
- ********
-
- If you want to add a simple device (specifically, a black-and-white
- printer), you probably don't need to read the rest of this document; just
- use the code in an existing driver as a guide. The Epson and BubbleJet
- drivers (gdevepsn.c and gdevbj10.c) are good models for dot-matrix
- printers, which require presenting the data for many scan lines at once;
- the DeskJet/LaserJet drivers (gdevdjet.c) are good models for laser
- printers, which take a single scan line at a time but support data
- compression. (For color printers, there are unfortunately no good models:
- the two major color inkjet printer drivers, gdevcdj.c and gdevstc.c, are
- far too complex to read.)
-
- On the other hand, if you're writing a driver for some more esoteric
- device, you probably do need at least some of the information in the rest
- of this document. It might be a good idea for you to read it in
- conjunction with one of the existing drivers.
-
- Duplication of code, and sheer code volume, is a serious maintenance and
- distribution problem for Ghostscript. If your device is similar to an
- existing one, try to implement your driver by adding some parameterization
- to an existing driver rather than copying code. gdevepsn.c and gdevdjet.c
- are good examples of this approach.
-
- ********
- ******** Driver structure ********
- ********
-
- A device is represented by a structure divided into three parts:
-
- - procedures that are shared by all instances of each device;
-
- - parameters that are present in all devices but may be different
- for each device or instance; and
-
- - device-specific parameters that may be different for each instance.
-
- Normally, the procedure structure is defined and initialized at compile
- time. A prototype of the parameter structure (including both generic and
- device-specific parameters) is defined and initialized at compile time, but
- is copied and filled in when an instance of the device is created. Both of
- these structures should be declared as const, but for backward
- compatibility reasons are not.
-
- The gx_device_common macro defines the common structure elements, with the
- intent that devices define and export a structure along the following
- lines. Do not fill in the individual generic parameter values in the usual
- way for C structures: use the macros defined for this purpose in gxdevice.h
- or, if applicable, gdevprn.h.
-
- typedef struct smurf_device_s {
- gx_device_common;
- ... device-specific parameters ...
- } smurf_device;
- smurf_device far_data gs_smurf_device = {
- ... macro for generic parameter values ...,
- { ... procedures ... }, /* std_procs */
- ... device-specific parameter values if any ...
- };
-
- The device structure instance *must* have the name gs_smurf_device, where
- smurf is the device name used in devs.mak.
-
- All the device procedures are called with the device as the first argument.
- Since each device type is actually a different structure type, the device
- procedures must be declared as taking a gx_device * as their first
- argument, and must cast it to smurf_device * internally. For example, in
- the code for the "memory" device, the first argument to all routines is
- called dev, but the routines actually use mdev to reference elements of the
- full structure, by virtue of the definition
-
- #define mdev ((gx_device_memory *)dev)
-
- (This is a cheap version of "object-oriented" programming: in C++, for
- example, the cast would be unnecessary, and in fact the procedure table
- would be constructed by the compiler.)
-
- Structure definition
- --------------------
-
- You should consult the definition of struct gx_device_s in gxdevice.h for
- the complete details of the generic device structure. Some of the most
- important members of this structure for ordinary drivers are:
-
- const char *dname; /* the device name */
- bool is_open; /* true if device has been opened */
- gx_device_color_info color_info; /* color information */
- int width; /* width in pixels */
- int height; /* height in pixels */
-
- The name in the structure (dname) should be the same as the name in
- devs.mak.
-
- gx_device_common is a macro consisting of just the element definitions.
-
- For sophisticated developers only
- ---------------------------------
-
- If for any reason you need to change the definition of the basic device
- structure, or add procedures, you must change the following places:
-
- - This document and NEWS (if you want to keep the
- documentation up to date).
- - The definition of gx_device_common and/or the procedures
- in gxdevice.h.
- - Possibly, the default forwarding procedures declared in gxdevice.h
- and implemented in gdevnfwd.c.
- - The device procedure record completion routines in gdevdflt.c.
- - Possibly, the default device implementation in gdevdflt.c and
- gdevddrw.c.
- - If you are adding procedures that produce output, the bounding box
- device in gdevbbox.c.
- - The following devices that must have complete (non-defaulted)
- procedure vectors:
- - The null device in gdevnfwd.c.
- - The command list "device" in gxclist.c. This is
- not an actual device; it only defines procedures.
- - The "memory" devices in gdevmem.h and gdevm*.c.
- - The halftoning device in gdevht.c.
- - The clip list accumulation "device" in gxacpath.c.
- - The clipping "devices" in gxcpath.c and gxclip2.c.
- - The Pattern accumulation "device" in gxpcmap.c.
- - The hit detection "device" in zupath.c.
- - The generic printer device macros in gdevprn.h.
- - The generic printer device code in gdevprn.c.
- - The RasterOp source device in gdevmrop.c.
-
- You may also have to change the code for gx_default_get_params and/or
- gx_default_put_params (in gsdparam.c).
-
- You should not have to change any of the real devices in the standard
- Ghostscript distribution (listed in devs.mak) or any of your own devices,
- because all of them are supposed to use the macros in gxdevice.h or
- gdevprn.h to define and initialize their state.
-
- ********
- ******** Types and coordinates ********
- ********
-
- Coordinate system
- -----------------
-
- Since each driver specifies the initial transformation from user to device
- coordinates, the driver can use any coordinate system it wants, as long as a
- device coordinate will fit in an int. (This is only an issue on MS-DOS
- systems, where ints are only 16 bits. User coordinates are represented as
- floats.) Most current drivers use a coordinate system with (0,0) in the
- upper left corner, with X increasing to the right and Y increasing toward
- the bottom. However, there is supposed to be nothing in the rest of
- Ghostscript that assumes this, and indeed some drivers use a coordinate
- system with (0,0) in the lower left corner.
-
- Drivers must check (and, if necessary, clip) the coordinate parameters
- given to them: they should not assume the coordinates will be in bounds.
- The fit_fill and fit_copy macros in gxdevice.h are very helpful in doing
- this.
-
- Color definition
- ----------------
-
- Ghostscript represents colors internally as RGB or CMYK values. In
- communicating with devices, however, it assumes that each device has a
- palette of colors identified by integers (to be precise, elements of type
- gx_color_index). Drivers may provide a uniformly spaced gray ramp or
- color cube for halftoning, or they may do their own color approximation,
- or both.
-
- The color_info member of the device structure defines the color and
- gray-scale capabilities of the device. Its type is defined as follows:
-
- typedef struct gx_device_color_info_s {
- int num_components; /* 1 = gray only, 3 = RGB, */
- /* 4 = CMYK */
- int depth; /* # of bits per pixel */
- gx_color_value max_gray; /* # of distinct gray levels -1 */
- gx_color_value max_rgb; /* # of distinct color levels -1 */
- /* (only relevant if num_comp. > 1) */
- gx_color_value dither_gray; /* size of gray ramp for halftoning */
- gx_color_value dither_rgb; /* size of color cube ditto */
- /* (only relevant if num_comp. > 1) */
- } gx_device_color_info;
-
- The following macros (in gxdevice.h) provide convenient shorthands for
- initializing this structure for ordinary black-and-white or color devices:
-
- #define dci_black_and_white ...
- #define dci_color(depth,maxv,dither) ...
-
- The idea is that a device has a certain number of gray levels (max_gray +1)
- and a certain number of colors (max_rgb +1) that it can produce directly.
- When Ghostscript wants to render a given RGB or CMYK color as a device
- color, it first tests whether the color is a gray level. (If
- num_components is 1, it converts all colors to gray levels.) If so:
-
- - If max_gray is large (>= 31), Ghostscript asks the device to
- approximate the gray level directly. If the device returns a valid
- gx_color_index, Ghostscript uses it. Otherwise, Ghostscript assumes that
- the device can represent dither_gray distinct gray levels, equally spaced
- along the diagonal of the color cube, and uses the two nearest ones to the
- desired color for halftoning.
-
- If the color is not a gray level:
-
- - If max_rgb is large (>= 31), Ghostscript asks the device to
- approximate the color directly. If the device returns a valid
- gx_color_index, Ghostscript uses it. Otherwise, Ghostscript assumes that
- the device can represent dither_rgb * dither_rgb * dither_rgb distinct
- colors, equally spaced throughout the color cube, and uses two of the
- nearest ones to the desired color for halftoning.
-
- Types
- -----
-
- Here is a brief explanation of the various types that appear as parameters
- or results of the drivers.
-
- gx_color_value (defined in gxdevice.h)
-
- This is the type used to represent RGB or CMYK color values. It is
- currently equivalent to unsigned short. However, Ghostscript may use less
- than the full range of the type to represent color values:
- gx_color_value_bits is the number of bits actually used, and
- gx_max_color_value is the maximum value (equal to 2^gx_max_color_value_bits
- - 1).
-
- gx_device (defined in gxdevice.h)
-
- This is the device structure, as explained above.
-
- gs_matrix (defined in gsmatrix.h)
-
- This is a 2-D homogeneous coordinate transformation matrix, used by
- many Ghostscript operators.
-
- gx_color_index (defined in gxdevice.h)
-
- This is meant to be whatever the driver uses to represent a device
- color. For example, it might be an index in a color map, or it might be
- R, G, and B values packed into a single integer. Ghostscript doesn't ever
- do any computations with gx_color_index values: it gets them from
- map_rgb_color or map_cmyk_color and hands them back as arguments to
- several other procedures. The special value gx_no_color_index (defined as
- (gx_color_index)(-1)) means "transparent" for some of the procedures. The
- type definition is simply:
-
- typedef unsigned long gx_color_index;
-
- gs_param_list (defined in gsparam.h)
-
- This is a parameter list, which is used to read and set attributes
- in a device. See the comments in gsparam.h, and the description of the
- get_params and put_params procedures below, for more detail.
-
- gx_tile_bitmap (defined in gxbitmap.h)
- gx_strip_bitmap (defined in gxbitmap.h)
-
- These structure types represent bitmaps to be used as a tile for
- filling a region (rectangle). gx_tile_bitmap is an older type lacking shift
- and rep_shift; gx_strip_bitmap has superseded it, and it should not be used
- in new code. Here is a copy of the relevant part of the file:
-
- /*
- * Structure for describing stored bitmaps.
- * Bitmaps are stored bit-big-endian (i.e., the 2^7 bit of the first
- * byte corresponds to x=0), as a sequence of bytes (i.e., you can't
- * do word-oriented operations on them if you're on a little-endian
- * platform like the Intel 80x86 or VAX). Each scan line must start on
- * a (32-bit) word boundary, and hence is padded to a word boundary,
- * although this should rarely be of concern, since the raster and width
- * are specified individually. The first scan line corresponds to y=0
- * in whatever coordinate system is relevant.
- *
- * For bitmaps used as halftone tiles, we may replicate the tile in
- * X and/or Y, but it is still valuable to know the true tile dimensions
- * (i.e., the dimensions prior to replication). Requirements:
- * width % rep_width = 0
- * height % rep_height = 0
- *
- * For halftones at arbitrary angles, we provide for storing the halftone
- * data as a strip that must be shifted in X for different values of Y.
- * For an ordinary (non-shifted) halftone that has a repetition width of
- * W and a repetition height of H, the pixel at coordinate (X,Y)
- * corresponds to halftone pixel (X mod W, Y mod H), ignoring phase;
- * for a shifted halftone with shift S, the pixel at (X,Y) corresponds
- * to halftone pixel ((X + S * floor(Y/H)) mod W, Y mod H). Requirements:
- * strip_shift < rep_width
- * strip_height % rep_height = 0
- * shift = (strip_shift * (size.y / strip_height)) % rep_width
- */
- typedef struct gx_strip_bitmap_s {
- byte *data;
- int raster; /* bytes per scan line */
- gs_int_point size; /* width, height */
- gx_bitmap_id id;
- ushort rep_width, rep_height; /* true size of tile */
- ushort strip_height;
- ushort strip_shift;
- ushort shift;
- } gx_strip_bitmap;
-
- ********
- ******** Coding conventions ********
- ********
-
- All the driver procedures defined below that return int results return 0 on
- success, or an appropriate negative error code in the case of error
- conditions. The error codes are defined in gserrors.h; they correspond
- directly to the errors defined in the PostScript language reference
- manuals. The most common ones for drivers are:
-
- gs_error_invalidfileaccess
- An attempt to open a file failed.
-
- gs_error_ioerror
- An error occurred in reading or writing a file.
-
- gs_error_limitcheck
- An otherwise valid parameter value was too large for
- the implementation.
-
- gs_error_rangecheck
- A parameter was outside the valid range.
-
- gs_error_VMerror
- An attempt to allocate memory failed. (If this
- happens, the procedure should release all memory it
- allocated before it returns.)
-
- If a driver does return an error, it should use the return_error
- macro rather than a simple return statement, e.g.,
-
- return_error(gs_error_VMerror);
-
- This macro is defined in gx.h, which is automatically included by
- gdevprn.h but not by gserrors.h.
-
- Allocating storage
- ------------------
-
- While most drivers (especially printer drivers) follow a very similar
- template, there is one important coding convention that is not obvious from
- reading the code for existing drivers: Driver procedures must not use
- malloc to allocate any storage that stays around after the procedure
- returns. Instead, they must use gs_malloc and gs_free, which have slightly
- different calling conventions. (The prototypes for these are in
- gsmemory.h, which is included in gx.h, which is included in gdevprn.h.)
- This is necessary so that Ghostscript can clean up all allocated memory
- before exiting, which is essential in environments that provide only
- single-address-space multi-tasking (some versions of Microsoft Windows).
-
- char *gs_malloc(uint num_elements, uint element_size,
- const char *client_name);
-
- Like calloc, but unlike malloc, gs_malloc takes an element count
- and an element size. For structures, num_elements is 1 and element_size is
- sizeof the structure; for byte arrays, num_elements is the number of bytes
- and element_size is 1. Unlike calloc, gs_malloc does NOT clear the block
- of storage.
-
- The client_name is used for tracing and debugging. It must be a
- real string, not NULL. Normally it is the name of the procedure in which
- the call occurs.
-
- void gs_free(char *data, uint num_elements, uint element_size,
- const char *client_name);
-
- Unlike free, gs_free demands that num_elements and element_size be
- supplied. It also requires a client name, like gs_malloc.
-
- Driver instance allocation
- --------------------------
-
- All driver instances allocated by Ghostscript's standard allocator must
- point to a "structure descriptor" that tells the garbage collector how to
- trace pointers in the structure. For drivers that are registered in the
- normal way (using the makefile approach described above), no special care
- is needed as long as instances are only created by calling the
- gs_copydevice procedure defined in gsdevice.h. If you have a need to
- define devices that are not registered in this way, you must fill in the
- stype member in any dynamically allocated instances with a pointer to the
- same structure descriptor used to allocate the instance. For more
- information about structure descriptors, see gsmemory.h and gsstruct.h.
-
- ********
- ******** Printer drivers ********
- ********
-
- Printer drivers (which include drivers that write some kind of raster
- file) are especially simple to implement. Of the driver procedures
- defined in the next section, they only need implement two: map_rgb_color
- (or map_cmyk_color) and map_color_rgb. In addition, they must implement a
- print_page or print_page_copies procedure. There are a set of macros in
- gdevprn.h that generate the device structure for such devices, of which
- the simplest is prn_device; for an example, see gdevbj10.c. If you are
- writing a printer driver, we suggest you start by reading gdevprn.h and
- the subsection on "Color mapping" below; you may be able to ignore all the
- rest of the driver procedures.
-
- The print_page procedures are defined as follows:
-
- int (*print_page)(P2(gx_device_printer *, FILE *))
- int (*print_page_copies)(P3(gx_device_printer *, FILE *, int))
-
- This procedure must read out the rendered image from the device and
- write whatever is appropriate to the file. To read back one or more scan
- lines of the image, the print_page procedure must call one of the following
- procedures:
-
- int gdev_prn_copy_scan_lines(P4(gx_device_printer *pdev, int y, byte *str,
- uint size)
-
- For this procedure, str is where the data should be copied to, and size is
- the size of the buffer starting at str. This procedure returns the number
- of scan lines copied, or <0 for an error. str need not be aligned.
-
- int gdev_prn_get_bits(gx_device_printer *pdev, int y, byte *str,
- byte **actual_data)
-
- This procedure reads out exactly one scan line. If the scan line is
- available in the correct format already, *actual_data is set to point to it;
- otherwise, the scan line is copied to the buffer starting at str, and
- *actual_data is set to str. This saves a copying step most of the time.
- str need not be aligned; however, if *actual_data is set to point to an
- existing scan line, it will be aligned. (See the description of the
- get_bits procedure below for more details.)
-
- In either case, each row of the image is stored in the form described
- in the comment under gx_tile_bitmap above; each pixel takes the
- number of bits specified as color_info.depth in the device structure,
- and holds values returned by the device's map_{rgb,cmyk}_color
- procedure.
-
- The print_page procedure can determine the number of bytes required to hold
- a scan line by calling:
-
- uint gdev_prn_raster(P1(gx_device_printer *))
-
- For a very simple concrete example, we suggest reading the code in
- bit_print_page in gdevbit.c.
-
- If the device provides print_page, Ghostscript will call print_page the
- requisite number of times to print the desired number of copies; if the
- device provides print_page_copies, Ghostscript will call print_page_copies
- once per page, passing it the desired number of copies.
-
- ********
- ******** Driver procedures ********
- ********
-
- Most of the procedures that a driver may implement are optional. If a
- device doesn't supply an optional procedure <proc>, the entry in the
- procedure structure may be either gx_default_<proc>, e.g.
- gx_default_tile_rectangle, or NULL or 0. (The device procedure must also
- call the gx_default_ procedure if it doesn't implement the function for
- particular values of the arguments.) Since C compilers supply 0 as the
- value for omitted structure elements, this convention means that
- statically initialized procedure structures will continue to work even if
- new (optional) members are added.
-
- Life cycle
- ----------
-
- A device instance start out life in a closed state. In this state, no
- output operations will occur. Only the following procedures may be called:
- open_device
- get_initial_matrix
- get_params
- put_params
-
- When setdevice installs a device instance in the graphics state, it checks
- whether the instance is closed or open. If the instance is closed,
- setdevice calls the open routine, and then sets the state to open.
-
- There is currently no user-accessible operation to close a device instance.
- Device instances are only closed when they are about to be freed, which
- occurs in three situations:
-
- - When a 'restore' occurs, if the instance was created since the
- corresponding 'save';
-
- - By the garbage collector, if the instance is no longer accessible;
-
- - When Ghostscript exits (terminates).
-
- Open/close/sync
- ---------------
-
- int (*open_device)(P1(gx_device *)) [OPTIONAL]
-
- Open the device: do any initialization associated with making the
- device instance valid. This must be done before any output to the device.
- The default implementation does nothing.
-
- void (*get_initial_matrix)(P2(gx_device *, gs_matrix *)) [OPTIONAL]
-
- Construct the initial transformation matrix mapping user
- coordinates (nominally 1/72" per unit) to device coordinates. The default
- procedure computes this from width, height, and x/y_pixels_per_inch on the
- assumption that the origin is in the upper left corner, i.e.
- xx = x_pixels_per_inch/72, xy = 0,
- yx = 0, yy = -y_pixels_per_inch/72,
- tx = 0, ty = height.
-
- int (*sync_output)(P1(gx_device *)) [OPTIONAL]
-
- Synchronize the device. If any output to the device has been
- buffered, send / write it now. Note that this may be called several times
- in the process of constructing a page, so printer drivers should NOT
- implement this by printing the page. The default implementation does
- nothing.
-
- int (*output_page)(P3(gx_device *, int num_copies, int flush)) [OPTIONAL]
-
- Output a fully composed page to the device. The num_copies
- argument is the number of copies that should be produced for a hardcopy
- device. (This may be ignored if the driver has some other way to specify
- the number of copies.) The flush argument is true for showpage, false for
- copypage. The default definition just calls sync_output. Printer drivers
- should implement this by printing and ejecting the page.
-
- int (*close_device)(P1(gx_device *)) [OPTIONAL]
-
- Close the device: release any associated resources. After this,
- output to the device is no longer allowed. The default implementation
- does nothing.
-
- Color/alpha mapping
- -------------------
-
- A given driver normally will implement either map_rgb_color or
- map_cmyk_color, but not both. Black-and-white drivers do not need to
- implement either one. Note that the map_xxx_color procedures must not
- return gx_no_color_index (all 1's).
-
- gx_color_index (*map_rgb_color)(P4(gx_device *, gx_color_value red,
- gx_color_value green, gx_color_value blue)) [OPTIONAL]
-
- Map a RGB color to a device color. The range of legal values of
- the RGB arguments is 0 to gx_max_color_value. The default algorithm uses
- the map_cmyk_color procedure if the driver supplies one, otherwise returns
- 1 if any of the values exceeds gx_max_color_value/2, 0 otherwise.
-
- Ghostscript assumes that for devices that have color capability
- (i.e., color_info.num_components > 1), map_rgb_color returns a color index
- for a gray level (as opposed to a non-gray color) iff red = green = blue.
-
- gx_color_index (*map_cmyk_color)(P5(gx_device *, gx_color_value cyan,
- gx_color_value magenta, gx_color_value yellow, gx_color_value black))
- [OPTIONAL]
-
- Map a CMYK color to a device color. The range of legal values of
- the CMYK arguments is 0 to gx_max_color_value. The default algorithm
- calls the map_rgb_color procedure, with suitably transformed arguments.
-
- Ghostscript assumes that for devices that have color capability
- (i.e., color_info.num_components > 1), map_cmyk_color returns a color
- index for a gray level (as opposed to a non-gray color) iff cyan = magenta
- = yellow.
-
- int (*map_color_rgb)(P3(gx_device *, gx_color_index color,
- gx_color_value rgb[3])) [OPTIONAL]
-
- Map a device color code to RGB values. The default algorithm
- returns (0 if color==0 else gx_max_color_value) for all three components.
-
- gx_color_index (*map_rgb_alpha_color)(P5(gx_device *, gx_color_value red,
- gx_color_value green, gx_color_value blue, gx_color_value alpha)) [OPTIONAL]
-
- Map a RGB color and an opacity value to a device color. The range
- of legal values of the RGB and alpha arguments is 0 to gx_max_color_value;
- alpha = 0 means transparent, alpha = gx_max_color_value means fully
- opaque. The default is to use the map_rgb_color procedure and ignore
- alpha.
-
- Note that if a driver implements map_rgb_alpha_color, it must also
- implement map_rgb_color, and must implement them in such a way that
- map_rgb_alpha_color(dev, r, g, b, gx_max_color_value) returns the same
- value as map_rgb_color(dev, r, g, b).
-
- Note that there is no map_cmyk_alpha_color procedure. CMYK
- devices currently do not support variable opacity; alpha is ignored on
- such devices.
-
- typedef enum { go_text, go_graphics } graphic_object_type;
- int (*get_alpha_bits)(P4(gx_device *dev, graphic_object_type type)) [OPTIONAL]
-
- Return the number of alpha (opacity) bits that should be used in
- rendering an object of the given type. The default value is 1; the only
- values allowed are 1, 2, and 4.
-
- Drawing
- -------
-
- All drawing operations use device coordinates and device color values.
-
- int (*fill_rectangle)(P6(gx_device *, int x, int y,
- int width, int height, gx_color_index color))
-
- Fill a rectangle with a color. The set of pixels filled is
- {(px,py) | x <= px < x + width and y <= py < y + height}. In other words,
- the point (x,y) is included in the rectangle, as are (x+w-1,y), (x,y+h-1),
- and (x+w-1,y+h-1), but *not* (x+w,y), (x,y+h), or (x+w,y+h). If width <=
- 0 or height <= 0, fill_rectangle should return 0 without drawing anything.
-
- Note that fill_rectangle is the only non-optional procedure in the
- driver interface.
-
- int (*draw_line)(P6(gx_device *, int x0, int y0, int x1, int y1,
- gx_color_index color)) [OPTIONAL]
-
- Draw a minimum-thickness line from (x0,y0) to (x1,y1). The
- precise set of points to be filled is defined as follows. First, if y1 <
- y0, swap (x0,y0) and (x1,y1). Then the line includes the point (x0,y0)
- but not the point (x1,y1). If x0=x1 and y0=y1, draw_line should return 0
- without drawing anything.
-
- Bitmap imaging
- --------------
-
- Bitmap (or pixmap) images are stored in memory in a nearly standard way.
- The first byte corresponds to (0,0) in the image coordinate system: bits
- (or polybit color values) are packed into it left-to-right. There may be
- padding at the end of each scan line: the distance from one scan line to
- the next is always passed as an explicit argument.
-
- int (*copy_mono)(P11(gx_device *, const unsigned char *data, int data_x,
- int raster, gx_bitmap_id id, int x, int y, int width, int height,
- gx_color_index color0, gx_color_index color1)) [OPTIONAL]
-
- Copy a monochrome image (similar to the PostScript image operator).
- Each scan line is raster bytes wide. Copying begins at (data_x,0) and
- transfers a rectangle of the given width and height to the device at device
- coordinate (x,y). (If the transfer should start at some non-zero y value in
- the data, the caller can adjust the data address by the appropriate multiple
- of the raster.) The copying operation writes device color color0 at each
- 0-bit, and color1 at each 1-bit: if color0 or color1 is gx_no_color_index,
- the device pixel is unaffected if the image bit is 0 or 1 respectively. If
- id is different from gx_no_bitmap_id, it identifies the bitmap contents
- unambiguously; a call with the same id will always have the same data,
- raster, and data contents.
-
- This operation, with color0 = gx_no_color_index, is the workhorse
- for text display in Ghostscript, so implementing it efficiently is very
- important.
-
- int (*tile_rectangle)(P10(gx_device *, const gx_tile_bitmap *tile,
- int x, int y, int width, int height,
- gx_color_index color0, gx_color_index color1,
- int phase_x, int phase_y)) [OPTIONAL] [OBSOLETE]
-
- This procedure is still supported, but has been superseded by
- strip_tile_rectangle. New drivers should implement strip_tile_rectangle; if
- they cannot cope with non-zero shift values, they should test for this
- explicitly and call the default implementation
- (gx_default_strip_tile_rectangle) if shift != 0. Clients should call
- strip_tile_rectangle, not tile_rectangle.
-
- int (*strip_tile_rectangle)(P10(gx_device *, const gx_strip_bitmap *tile,
- int x, int y, int width, int height,
- gx_color_index color0, gx_color_index color1,
- int phase_x, int phase_y)) [OPTIONAL]
-
- Tile a rectangle. Tiling consists of doing multiple copy_mono
- operations to fill the rectangle with copies of the tile. The tiles are
- aligned with the device coordinate system, to avoid "seams".
- Specifically, the (phase_x, phase_y) point of the tile is aligned with the
- origin of the device coordinate system. (Note that this is backwards from
- the PostScript definition of halftone phase.) phase_x and phase_y are
- guaranteed to be in the range [0..tile->width) and [0..tile->height)
- respectively.
-
- If color0 and color1 are both gx_no_color_index, then the tile is
- a color pixmap, not a bitmap: see the next section.
-
- This operation is the workhorse for halftone filling in Ghostscript,
- so implementing it efficiently for solid tiles (i.e., where either color0
- and color1 are both gx_no_color_index, for colored halftones, or neither one
- is gx_no_color_index, for monochrome halftones) is very important.
-
- Pixmap imaging
- --------------
-
- Pixmaps are just like bitmaps, except that each pixel occupies more than
- one bit. All the bits for each pixel are grouped together (this is
- sometimes called "chunky" or "Z" format). For copy_color, the number of
- bits per pixel is given by the color_info.depth parameter in the device
- structure: the legal values are 1, 2, 4, 8, 16, 24, or 32. The pixel
- values are device color codes (i.e., whatever it is that map_rgb_color
- returns).
-
- int (*copy_color)(P9(gx_device *, const unsigned char *data, int data_x,
- int raster, gx_bitmap_id id, int x, int y, int width, int height))
- [OPTIONAL]
-
- Copy a color image with multiple bits per pixel. The raster is in
- bytes, but x and width are in pixels, not bits. If id is different from
- gx_no_bitmap_id, it identifies the bitmap contents unambiguously; a call
- with the same id will always have the same data, raster, and data contents.
-
- We do not provide a separate procedure for tiling with a pixmap; instead,
- tile_rectangle can also take colored tiles. This is indicated by the
- color0 and color1 arguments both being gx_no_color_index. In this case,
- as for copy_color, the raster and height in the "bitmap" are interpreted
- as for real bitmaps, but the x and width are in pixels, not bits.
-
- int (*copy_alpha)(P11(gx_device *dev, const unsigned char *data, int data_x,
- int raster, gx_bitmap_id id, int x, int y, int width, int height,
- gx_color_index color, int depth)) [OPTIONAL]
-
- Fill a given region with a given color modified by an individual
- alpha value for each pixel. depth, the number of bits per pixel, is
- either 2 or 4, and in any case is always a value returned by a previous
- call on the get_alpha_bits procedure. Note that if get_alpha_bits always
- returns 1, this procedure will never be called.
-
- Bitmap/pixmap imaging
- ---------------------
-
- int (*copy_rop)(P15(gx_device *dev,
- const byte *sdata, int sourcex, uint sraster, gx_bitmap_id id,
- const gx_color_index *scolors,
- const gx_tile_bitmap *texture, const gx_color_index *tcolors,
- int x, int y, int width, int height,
- int phase_x, int phase_y, int command)) [OPTIONAL]
-
- This procedure is still supported, but has been superseded by
- strip_copy_rop. New drivers should implement strip_copy_rop; if they cannot
- cope with non-zero shift values in the texture, they should test for this
- explicitly and call the default implementation (gx_default_strip_copy_rop)
- if shift != 0. Clients should call strip_copy_rop, not copy_rop.
-
- int (*strip_copy_rop)(P15(gx_device *dev,
- const byte *sdata, int sourcex, uint sraster, gx_bitmap_id id,
- const gx_color_index *scolors,
- const gx_strip_bitmap *texture, const gx_color_index *tcolors,
- int x, int y, int width, int height,
- int phase_x, int phase_y, int command)) [OPTIONAL]
-
- Combine an optional source image S (as for copy_mono or copy_color)
- and an optional texture T (a tile, as for tile_rectangle) with the existing
- bitmap or pixmap D held by the driver, pixel by pixel, using any 3-input
- Boolean operation as modified by "transparency" flags: schematically, set D
- = f(D,S,T), computing f in RGB space rather than using actual device pixel
- values. S and T may each (independently) be a solid color, a bitmap with
- "foreground" and "background" colors, or a pixmap. This is a complex (and
- currently rather slow) operation. The arguments are as follows:
-
- dev - the device, as for all driver procedures
-
- sdata, sourcex, sraster, id, scolors - specify S, see below
-
- texture, tcolors - specify T, see below
-
- x, y, width, height - as for the other copy/fill procedures
-
- phase_x, phase_y - part of T specification, see below
-
- command - see below
-
- S specification
- ...............
-
- As noted above, the source (S) may be a solid color, a bitmap, or a pixmap.
-
- If S is a solid color:
-
- - sdata, sourcex, sraster, and id are irrelevant.
-
- - scolors points to two gx_color_index values; scolors[0] =
- scolors[1] = the color.
-
- If S is a bitmap:
-
- - sdata, sourcex, sraster, and id arguments are as for copy_mono or
- copy_color (data, data_x, raster, id), and specify a source bitmap.
-
- - scolors points to two gx_color_index values; scolors[0] is the
- background color (the color corresponding to 0-bits in the bitmap),
- scolors[1] is the foreground color (the color corresponding to
- 1-bits in the bitmap).
-
- If S is a pixmap:
-
- - sdata, sourcex, sraster, and id arguments are as for copy_mono or
- copy_color (data, data_x, raster, id), and specify a source pixmap
- whose depth is the same as the depth of the destination.
-
- - scolors is NULL.
-
- Note that if the source is a bitmap with background=0 and foreground=1, and
- the destination is 1 bit deep, then the source can be treated as a pixmap
- (scolors=NULL).
-
- T specification
- ...............
-
- Similar to the source, the texture (T) may be a solid color, a bitmap, or a
- pixmap.
-
- If T is a solid color:
-
- - The texture pointer is irrelevant.
-
- - tcolors points to two gx_color_index values; tcolors[0] =
- tcolors[1] = the color.
-
- If T is a bitmap:
-
- - The texture argument points to a gx_tile_bitmap, as for the
- tile_rectangle procedure. Similarly, phase_x and phase_y specify
- the offset of the texture relative to the device coordinate system
- origin, again as for tile_rectangle. The tile is a bitmap (1 bit
- per pixel).
-
- - tcolors points to two gx_color_index values; tcolors[0] is the
- background color (the color corresponding to 0-bits in the bitmap),
- tcolors[1] is the foreground color (the color corresponding to
- 1-bits in the bitmap).
-
- If T is a pixmap:
-
- - The texture argument points to a gx_tile_bitmap whose depth is
- the same as the depth of the destination.
-
- - tcolors is NULL.
-
- Again, if the texture is a bitmap with background=0 and foreground=1, and
- the destination depth is 1, the texture bitmap can be treated as a pixmap
- (tcolors=NULL).
-
- Note that while a source bitmap or pixmap has the same width and height as
- the destination, a texture bitmap or pixmap has its own width and height
- specified in the gx_tile_bitmap structure, and is replicated and/or clipped
- as needed.
-
- f specification
- ...............
-
- Command indicates the raster operation and transparency as follows:
-
- bits 7-0: raster op
- bit 8: 0 if source opaque, 1 if source transparent
- bit 9: 0 if texture opaque, 1 if texture transparent
- bits ?-10: unused, must be 0
-
- The raster operation follows the Microsoft and H-P specification. It is an
- 8-element truth table that specifies the output value for each of the
- possible 2x2x2 input values as follows:
-
- Bit Texture Source Destination
- 7 1 1 1
- 6 1 1 0
- 5 1 0 1
- 4 1 0 0
- 3 0 1 1
- 2 0 1 0
- 1 0 0 1
- 0 0 0 0
-
- Transparency affects the output in the following way. A source or texture
- pixel is considered transparent if its value is all 1's (e.g., 1 for
- bitmaps, 0xffffff for 24-bit RGB pixmaps) *and* the corresponding
- transparency bit is set in the command. For each pixel, the result of the
- Boolean operation is written into the destination iff neither the source nor
- the texture pixel is transparent. (Note that the H-P RasterOp
- specification, on which this is based, specifies that if the source and
- texture are both all 1's and the command specifies transparent source and
- opaque texture, the result *should* be written in the output. We think this
- is an error in the documentation.)
-
- Notes
- .....
-
- Note that copy_rop is defined to operate on pixels in RGB space, again
- following the H-P and Microsoft specification. For devices that don't use
- RGB (or gray-scale with black=0, white=all 1's) as their native color
- representation, the implementation of copy_rop must convert to RGB or gray
- space, do the operation, and convert back (or do the equivalent of this).
-
- Here are the copy_rop equivalents of the most important previous imaging
- calls. Note that rop3_S may be replaced by any other Boolean operation.
- For monobit devices, we assume that black = 1. We assume the following
- declaration:
- static const gx_color_index white2[2] = { 1, 1 };
-
- /* For all devices: */
- (*fill_rectangle)(dev, x, y, w, h, color) ==>
-
- { gx_color_index colors[2];
- colors[0] = colors[1] = color;
- (*dev_proc(dev, copy_rop))(dev, NULL, 0, 0, gx_no_bitmap_id, colors,
- NULL, colors /*irrelevant*/,
- x, y, w, h, 0, 0, rop3_S);
- }
-
- /* For black-and-white devices only: */
- (*copy_mono)(dev, base, sourcex, sraster, id,
- x, y, w, h, (gx_color_index)0, (gx_color_index)1) ==>
-
- (*dev_proc(dev, copy_rop))(dev, base, sourcex, sraster, id, NULL,
- NULL, white2 /*irrelevant*/,
- x, y, w, h, 0, 0, rop3_S);
-
- /* For color devices, where neither color0 nor color1 is gx_no_color_index: */
- (*copy_mono)(dev, base, sourcex, sraster, id,
- x, y, w, h, color0, color1) ==>
-
- { gx_color_index colors[2];
- colors[0] = color0, colors[1] = color1;
- (*dev_proc(dev, copy_rop))(dev, base, sourcex, sraster, id, colors,
- NULL, white2 /*irrelevant*/,
- x, y, w, h, 0, 0, rop3_S);
- }
-
- /* For black-and-white devices only: */
- (*copy_mono)(dev, base, sourcex, sraster, id,
- x, y, w, h, gx_no_color_index, (gx_color_index)1) ==>
-
- (*dev_proc(dev, copy_rop))(dev, base, sourcex, sraster, id, NULL,
- NULL, white2 /*irrelevant*/,
- x, y, w, h, 0, 0,
- rop3_S | lop_S_transparent);
-
- /* For all devices: */
- (*copy_color)(dev, base, sourcex, sraster, id,
- x, y, w, h) ==> [same as first copy_mono above]
-
- /* For black-and-white devices only: */
- (*tile_rectangle)(dev, tile, x, y, w, h,
- (gx_color_index)0, (gx_color_index)1, px, py) ==>
-
- (*dev_proc(dev, copy_rop))(dev, NULL, 0, 0, gx_no_bitmap_id,
- white2 /*irrelevant*/,
- tile, NULL,
- x, y, w, h, px, py, rop3_T)
-
- Polygons
- --------
-
- In addition to the lowest-level drawing operations that take integer device
- coordinates and pure device colors, the driver interface includes
- higher-level operations that draw polygons using fixed-point coordinates,
- possibly halftoned colors, and possibly a non-default logical operation.
-
- The fill_* drawing operations all use the center-of-pixel rule: a pixel is
- colored iff its center falls within the polygonal region being filled. If a
- pixel center (X+0.5,Y+0.5) falls exactly on the boundary, the pixel is
- filled iff the boundary is horizontal and the filled region is above it, or
- the boundary is not horizontal and the filled region is to the right of it.
-
- int (*fill_trapezoid)(P10(gx_device *dev,
- fixed fx0, fixed fw0, fixed fy0,
- fixed fx1, fixed fw1, fixed fh, bool swap_axes,
- const gx_drawing_color *pdcolor, gs_logical_operation_t lop)) [OPTIONAL]
-
- Fill a trapezoid whose parallel sides are parallel to a coordinate
- axis. The corners are (fx0,fy0), (fx0+fw0,fy0), (fx1,fy0+fh), and
- (fx1+fw1,fy0+fy). We require fw0 >= 0, fw1 >= 0, and fh >= 0; if fw0 = 0 or
- fw1 = 0, the trapezoid is actually a triangle. If swap_axes is set, the
- meanings of X and Y are interchanged.
-
- int (*fill_parallelogram)(P9(gx_device *dev,
- fixed px, fixed py, fixed ax, fixed ay, fixed bx, fixed by,
- const gx_drawing_color *pdcolor, gs_logical_operation_t lop)) [OPTIONAL]
-
- Fill a parallelogram whose corners are (px,py), (px+ax,py+ay),
- (px+bx,py+by), and (px+ax+bx,py+ay+by). There are no constraints on the
- values of any of the parameters, so the parallelogram may have any
- orientation relative to the coordinate axes.
-
- int (*fill_triangle)(P9(gx_device *dev,
- fixed px, fixed py, fixed ax, fixed ay, fixed bx, fixed by,
- const gx_drawing_color *pdcolor, gs_logical_operation_t lop)) [OPTIONAL]
-
- Fill a triangle whose corners are (px,py), (px+ax,py+ay), and
- (px+bx,py+by).
-
- int (*draw_thin_line)(P7(gx_device *dev,
- fixed fx0, fixed fy0, fixed fx1, fixed fy1,
- const gx_drawing_color *pdcolor, gs_logical_operation_t lop)) [OPTIONAL]
-
- Draw a one-pixel-wide line from (fx0,fy0) to (fx1,fy1). This
- replaces the older draw_line procedure, which required integer coordinates,
- a pure color, and no logical operation.
-
- High-level drawing
- ------------------
-
- In addition to the low-level drawing operations described above, the driver
- interface provides a set of high-level operations. Normally these will have
- their default implementation, which converts the high-level operation to the
- low-level ones just described; however, drivers that generate high-level
- output formats such as CGM, or communicate with devices that have firmware
- for higher-level operations such as polygon fills, may implement these
- high-level operations directly.
-
- For more details, please consult the source code, specifically:
- gxpaint.h - defines gx_fill_params, gx_stroke_params
- gxfixed.h - defines fixed, gs_fixed_point (used by gx_*_params)
- gxistate.h - defines gs_imager_state (used by gx_*_params)
- gxline.h - defines gx_line_params (used by gs_imager_state)
- gslparam.h - defines line cap/join values (used by gx_line_params)
- gxmatrix.h - defines gs_matrix_fixed (used by gs_imager_state)
- g[s,x,z]path.h - defines gx_path
- g[x,z]cpath.h - defines gx_clip_path
-
- int (*fill_path)(P6(gx_device *dev,
- const gx_imager_state *pis, gx_path *ppath, const gx_fill_params *params,
- const gx_drawing_color *pdcolor, const gx_clip_path *pcpath)) [OPTIONAL]
-
- Fill the given path, clipped by the given clip path, according to
- the given parameters, with the given color. The clip path pointer may be
- NULL, meaning do not clip.
-
- int (*stroke_path)(P6(gx_device *dev,
- const gx_imager_state *pis, gx_path *ppath, const gx_stroke_params *params,
- const gx_drawing_color *pdcolor, const gx_clip_path *pcpath)) [OPTIONAL]
-
- Stroke the given path, clipped by the given clip path, according to
- the given parameters, with the given color. The clip path pointer may be
- NULL, meaning do not clip.
-
- int (*fill_mask)(P13(gx_device *dev,
- const byte *data, int data_x, int raster, gx_bitmap_id id,
- int x, int y, int width, int height,
- const gx_drawing_color *pdcolor, int depth,
- int command, const gx_clip_path *pcpath)) [OPTIONAL]
-
- Color the 1-bits in the given mask (or according to the alpha
- values, if depth > 1), clipped by the given clip path, with the given color
- and logical operation. The clip path pointer may be NULL, meaning do not
- clip. The parameters data, ..., height are as for copy_mono; depth is as
- for copy_alpha; command is as for copy_rop.
-
- High-level bitmap imaging
- -------------------------
-
- Similar to the high-level interface for fill/stroke graphics, a high-level
- interface exists for bitmap images. All of the procedures in this part of
- the interface are optional; however, if begin_image is defined, image_data
- and end_image also must be defined.
-
- A bitmap image is defined by a gs_image_t structure. We only summarize this
- structure here.
-
- typedef struct gs_image_s {
- int Width; /* Width of source image in pixels */
- int Height; /* Height ditto */
- gs_matrix ImageMatrix; /* transformation from 1x1 image space to */
- /* user space defined by imager CTM */
- int BitsPerComponent;
- const gs_color_space *ColorSpace;
- float Decode[8]; /* linear remapping of input values */
- bool Interpolate; /* smooth image if true */
- bool ImageMask; /* true = mask, false = solid image */
- bool adjust; /* expand bits if mask */
- bool CombineWithColor; /* use drawing color as RasterOp texture */
- } gs_image_t;
- typedef enum {
- gs_image_format_chunky = 0,
- gs_image_format_component_planar = 1
- } gs_image_format_t;
-
- For more details, consult the source code in
- gsiparam.h - defines parameters for an image
-
- int (*begin_image)(P9(gx_device *dev,
- const gs_imager_state *pis, const gs_image_t *pim, gs_image_format_t format,
- gs_int_rect *prect, const gx_drawing_color *pdcolor,
- const gx_clip_path *pcpath, gs_memory_t *memory, void **pinfo)) [OPTIONAL]
-
- Begin the transmission of an image. Zero or more calls of
- image_data will follow, and then a call of end_image. The parameters of
- begin_image are as follows:
-
- pis - pointer to an imager state. The only relevant elements of the
- imager state are the CTM (coordinate transformation matrix), the logical
- operation (RasterOp/transparency), and the color rendering information.
-
- pim - pointer to the gs_image_t structure that defines the image
- parameters.
-
- format - defines how pixels are represented for image_data. See the
- description of image_data below.
-
- prect - if not NULL, defines a subrectangle of the image; only the
- data for this subrectangle will be passed to image_data, and only this
- subrectangle should be drawn.
-
- pdcolor - defines a drawing color, only needed for masks or if
- CombineWithColor is true.
-
- pcpath - if not NULL, defines an optional clipping path.
-
- memory - defines the allocator to be used for allocating bookkeeping
- information.
-
- pinfo - the implementation should return a pointer to its
- bookkeeping structure here.
-
- begin_image is expected to allocate a structure for its bookkeeping
- needs, using the allocator defined by the memory parameter, and return it in
- *pinfo. begin_image should not assume that the structures in *pim, *prect,
- or *pdcolor will survive the call on begin_image (except for the color space
- in *pim->ColorSpace): it should copy any necessary parts of them into its
- own bookkeeping structure. It may, however, assume that *pis, *pcpath, and
- of course *memory will live at least until end_image is called.
-
- int (*image_data)(P6(gx_device *dev,
- void *info, const byte **planes, int data_x, uint raster, int height))
- [OPTIONAL]
-
- This call provides more of the image source data: specifically,
- height rows, with Width pixels supplied for each row.
-
- The data for each row are packed big-endian within each byte, as for
- copy_color. The raster (number of bytes per row) may include some padding
- at the end of each row. Note that for non-mask images, the input data may
- be in any color space and may have any number of bits per component (1, 2,
- 4, 8, 12); currently mask images always have 1 bit per component, but in the
- future, they might allow multiple bits of alpha. Note also that each call
- of image_data passes complete pixels: e.g., for a chunky image with 24 bits
- per pixel, each call of image_data passes 3N bytes of data (specifically, 3
- * Width * height).
-
- The interpretation of planes depends on the format argument of
- begin_image:
-
- -- If format is gs_image_format_chunky, planes[0] points to data in
- "chunky" format, in which the components follow each other (e.g.,
- RGBRGBRGB....)
-
- -- If format is gs_image_format_component_planar, planes[0 .. N-1]
- point to data for the N components (e.g., N=3 for RGB data); each plane
- contains samples for a single component, e.g., RR..., GG..., BB.... Note
- that the planes are divided by component, not by bit: for example, for
- 24-bit RGB data, N=3, with 8-bit values in each plane of data. Someday we
- may add gs_image_format_bit_planar, specifying that each plane would contain
- only a single bit of the pixel value, but this is not currently implemented.
-
- If, as a result of this call, image_data has been called with all
- the data for the (sub-)image, it returns 1; otherwise, it returns 0 or an
- error code as usual.
-
- image_data, unlike most other driver procedures that take bitmaps as
- arguments, does not require the data to be aligned in any way.
-
- int end_image(P3(gx_device *dev,
- void *info, bool draw_last)) [OPTIONAL]
-
- Finish processing an image, either because all data have been
- supplied or because the caller has decided to abandon this image. end_image
- may be called at any time after begin_image. It should free the info
- structure and any subsidiary structures. If draw_last is true, it should
- finish drawing any buffered lines of the image.
-
- While there will almost never be more than one image enumeration in
- progress -- i.e., after a begin_image, end_image will almost always be
- called before the next begin_image -- driver code should not rely on this
- property; in particular, it should store all information regarding the image
- in the info structure, not in the driver structure.
-
- Note that if begin_image saves its parameters in the info structure,
- it can decide on each call whether to use its own algorithms or to use the
- default implementation. (It may need to call gx_default_begin/end_image
- partway through.) [A later revision of this document may include an example
- here.]
-
- Reading bits back
- -----------------
-
- int (*get_bits)(P4(gx_device *, int y, byte *str, byte **actual_data))
- [OPTIONAL]
-
- Read one scan line of bits back from the device into the area
- starting at str, namely, scan line y. If the bits cannot be read back
- (e.g., from a printer), return -1; otherwise return 0. The contents of the
- bits beyond the last valid bit in the scan line (as defined by the device
- width) are unpredictable. str need not be aligned in any particular way.
-
- If actual_data is NULL, the bits are always returned at str. If
- actual_data is not NULL, get_bits may either copy the bits to str and set
- *actual_data = str, or it may leave the bits where they are and return a
- pointer to them in *actual_data. In the latter case, the bits are
- guaranteed to start on a 32-bit boundary and to be padded to a multiple of
- 32 bits; also in this case, the bits are not guaranteed to still be there
- after the next call on get_bits.
-
- Parameters
- ----------
-
- Devices may have an open-ended set of parameters, which are simply pairs
- consisting of a name and a value. The value may be of various types:
- integer (int or long), boolean, float, string, name, null, array of integer,
- or array of float. For example, the Name of a device is a string; the
- Margins of a device is an array of 2 floats. See gsparam.h for more
- details.
-
- If a device has parameters other than the ones applicable to all devices
- (or, in the case of printer devices, all printer devices), it must provide
- get_params and put_params procedures. If your device has parameters beyond
- those of a straightforward display or printer, we strongly advise using the
- _get_params and _put_params procedures in an existing device (for example,
- gdevcdj.c or gdevbit.c) as a model for your own code.
-
- int (*get_params)(P2(gx_device *dev, gs_param_list *plist)) [OPTIONAL]
-
- Read the parameters of the device into the parameter list at plist,
- using the param_write_* macros/procedures defined in gsparam.h.
-
- int (*put_params)(P2(gx_device *dev, gs_param_list *plist)) [OPTIONAL]
-
- Set the parameters of the device from the parameter list at plist,
- using the param_read_* macros/procedures defined in gsparam.h. All
- put_params procedures must use a "two-phase commit" algorithm; see gsparam.h
- for details.
-
- External fonts
- --------------
-
- Drivers may include the ability to display text. More precisely, they may
- supply a set of procedures that in turn implement some font and text
- handling capabilities. These procedures are documented in another file,
- xfonts.txt. The link between the two is the driver procedure that
- supplies the font/text procedures:
-
- xfont_procs *(*get_xfont_procs)(P1(gx_device *dev)) [OPTIONAL]
-
- Return a structure of procedures for handling external fonts and
- text display. A NULL value means that this driver doesn't provide this
- capability.
-
- For technical reasons, a second procedure is also needed:
-
- gx_device *(*get_xfont_device)(P1(gx_device *dev)) [OPTIONAL]
-
- Return the device that implements get_xfont_procs in a non-default
- way for this device, if any. Except for certain special internal devices,
- this is always the device argument.
-
- Page devices
- ------------
-
- gx_device *(*get_page_device)(P1(gx_device *dev)) [OPTIONAL]
-
- According to the Adobe specifications, some devices are "page
- devices" and some are not. This procedure returns NULL if the device is
- not a page device, or the device itself if it is a page device. In the
- case of forwarding devices, get_page_device returns the underlying page
- device (or NULL if the underlying device is not a page device).
-
- Miscellaneous
- -------------
-
- int (*get_band)(P3(gx_device *dev, int y, int *band_start)) [OPTIONAL]
-
- If the device is a band device, this procedure stores in *band_start
- the scan line (device Y coordinate) of the band that includes the given Y
- coordinate, and returns the number of scan lines in the band. If the device
- is not a band device, this procedure returns 0. The latter is the default
- implementation.
-
- void (*get_clipping_box)(P2(gx_device *dev, gs_fixed_rect *pbox))
- [OPTIONAL]
-
- Stores in *pbox a rectangle that defines the device's clipping
- region. For all but a few specialized devices, this is
- ((0,0),(width,height)).
-